#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "gd32f30x.h"
#include "delay.h"
#include "RTT_Debug.h"

#define USART1_DATA_ADDR      (USART1 + 0x04)   //串口2的数据寄存器十六进制地址值
#define MAX_BUF_SIZE           256
static uint8_t  g_recvDataBuf[MAX_BUF_SIZE];

typedef struct
{
	uint32_t uartNo;
	rcu_periph_enum rcuUart;
	rcu_periph_enum rcuGpio;
	uint32_t gpio;
	uint32_t txPin;
	uint32_t rxPin;
	uint8_t irq;
	uint32_t dmaNo;
	rcu_periph_enum rcuDma;
	dma_channel_enum dmaCh;
} UartHwInfo_t;

static UartHwInfo_t g_uartHwInfo = {USART1, RCU_USART1, RCU_GPIOA, GPIOA, GPIO_PIN_2, 
									GPIO_PIN_3, USART1_IRQn, DMA0, RCU_DMA0, DMA_CH5};

static void WifiGpioInit(void)
{
	rcu_periph_clock_enable(RCU_GPIOA);
	gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_7);
	
	rcu_periph_clock_enable(g_uartHwInfo.rcuGpio);
	gpio_init(g_uartHwInfo.gpio, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, g_uartHwInfo.txPin);
	gpio_init(g_uartHwInfo.gpio, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, g_uartHwInfo.rxPin);
}

static void WifiUartInit(uint32_t baudRate)
{
	/* 使能UART时钟；*/
	rcu_periph_clock_enable(g_uartHwInfo.rcuUart);
	/* 复位UART；*/
	usart_deinit (g_uartHwInfo.uartNo);
	/* 通过USART_CTL0寄存器的WL设置字长；*/ 
	//usart_word_length_set(g_uartHwInfo.uartNo, USART_WL_8BIT);
	/* 通过USART_CTL0寄存器的PCEN设置校验位；*/ 
	//usart_parity_config(g_uartHwInfo.uartNo, USART_PM_NONE);
	/* 在USART_CTL1寄存器中写STB[1:0]位来设置停止位的长度；*/ 
	//usart_stop_bit_set(g_uartHwInfo.uartNo, USART_STB_1BIT);
	/* 在USART_BAUD寄存器中设置波特率；*/ 
	usart_baudrate_set(g_uartHwInfo.uartNo, baudRate);
	/* 在USART_CTL0寄存器中设置TEN位，使能发送功能；*/
	usart_transmit_config(g_uartHwInfo.uartNo, USART_TRANSMIT_ENABLE);
	/* 在USART_CTL0寄存器中设置TEN位，使能接收功能；*/
	usart_receive_config(g_uartHwInfo.uartNo, USART_RECEIVE_ENABLE);
	/* 使能串口接收空闲中断；*/
	usart_interrupt_enable(g_uartHwInfo.uartNo, USART_INT_IDLE);
	/* 使能串口中断；*/
	nvic_irq_enable(g_uartHwInfo.irq, 0, 0);
	/* 在USART_CTL0寄存器中置位UEN位，使能UART；*/ 
	usart_enable(g_uartHwInfo.uartNo);
}

static void WifiDmaInit(void)
{
	/* 使能DMA时钟；*/
	rcu_periph_clock_enable(g_uartHwInfo.rcuDma);
	/* 复位DMA通道；*/
	dma_deinit(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh);
	dma_parameter_struct dmaStruct;
	/* 配置传输方向；*/ 
	dmaStruct.direction = DMA_PERIPHERAL_TO_MEMORY;
	/* 配置数据源地址；*/ 
	dmaStruct.periph_addr = USART1_DATA_ADDR;
	/* 配置源地址是固定的还是增长的；*/ 
	dmaStruct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
	/* 配置源数据传输位宽；*/ 
	dmaStruct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
	
	/* 配置数据目的地址；*/
	dmaStruct.memory_addr = (uint32_t)g_recvDataBuf;
	/* 配置目的地址是固定的还是增长的；*/ 
	dmaStruct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
	/* 配置目的数据传输位宽；*/ 
	dmaStruct.memory_width = DMA_MEMORY_WIDTH_8BIT;
	/* 配置数据传输最大次数；*/ 
	dmaStruct.number = MAX_BUF_SIZE;
	/* 配置DMA通道优先级；*/ 
	dmaStruct.priority = DMA_PRIORITY_HIGH;
	dma_init(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh, &dmaStruct);
	
	/* 使能UART接收数据使用DMA；*/ 
	usart_dma_receive_config(g_uartHwInfo.uartNo, USART_RECEIVE_DMA_ENABLE);
	/* 使能DMA通道；*/ 
	dma_channel_enable(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh);
}

void HwresetWifiModule(void)
{
	DBG_log("wifi module,now hwreset it!\n");
	gpio_bit_reset(GPIOA, GPIO_PIN_7);
	DelayNms(100);
	gpio_bit_set(GPIOA, GPIO_PIN_7);
}
	
void WifiModuleDrvInit(void)
{
	WifiGpioInit();
	WifiUartInit(115200);
	WifiDmaInit();
	HwresetWifiModule();
}


void USART1_IRQHandler(void)
{
	if (usart_interrupt_flag_get(g_uartHwInfo.uartNo, USART_INT_FLAG_IDLE) != RESET)
	{
		usart_interrupt_flag_clear(g_uartHwInfo.uartNo, USART_INT_FLAG_IDLE);  //第一步，读取stat0寄存器，清除IDLE标志位
		usart_data_receive(g_uartHwInfo.uartNo);                               //第二步，读取数据寄存器，清除IDLE标志位
		DBG_log("uart recv str:%s\n", g_recvDataBuf);
		dma_channel_disable(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh);
		dma_transfer_number_config(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh, MAX_BUF_SIZE);
		dma_channel_enable(g_uartHwInfo.dmaNo, g_uartHwInfo.dmaCh);
	}
}

char *RecvWifiModuleStr(void)
{
	return (char *)g_recvDataBuf;
}

void ClearRecvWifiStr(void)
{
	memset(g_recvDataBuf, 0, MAX_BUF_SIZE);
}

void SendWifiModuleStr(const char *sendStr)
{
	DBG_log("uart send str:%s\n", sendStr);
	while (*sendStr != '\0')
    {
		usart_data_transmit(g_uartHwInfo.uartNo, *sendStr);
		while (RESET == usart_flag_get(g_uartHwInfo.uartNo, USART_FLAG_TBE));
		sendStr++;
	}
}
